import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.imageio.ImageIO;
import javax.mail.Authenticator;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

import model.UserInfo;

public class FrameMain
{
    private final static String SUCCESS = "发送成功";
    private final static String LABEL_TEXT = "发送请求还有:";
    private final static String STEP_ONE = "准备数据中...";
    private final static String STEP_TWO = "数据准备完毕，准备发送...";
    private final static String STEP_THREE = "正在发送...";
    private final static String CHECKING = "登陆检查...";
    private final static String CHECKED_SUCCESS = "Bingo!!!";
    private final static String CHECKED_FAILED = "Sorry";
    private final static String SHUTDOWN_CMD = "Shutdown -s -t 120";
    private final static int STATUS_INDEX = 4;
    private static List<Map<String, String>> postDataList = new ArrayList<Map<String, String>>();
    private static long nextTime = 500;
    private static int count = 0;
    private final static JTable table = new JTable();
    private final static JCheckBox shutdownBox = new JCheckBox("发送完毕后自动关机");
    private static Object lockObj = new Object();
    private static int successCount = 0;
    private static boolean isSend = true;

    @SuppressWarnings("unchecked")
    public static void main(String[] args)
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(800, 500);
        f.setLocation(200, 200);
        
        Container content = f.getContentPane();
        String columns[] = {"证件号", "姓名", "型号", "邮箱", "状态"};
        final List<UserInfo> itemList = ExcelUtil.getBookItem();
        String title = "香港苹果IFC预订,今日" + itemList.size() + "单";
        f.setTitle(title);
        try
        {
            BufferedImage img = ImageIO.read(new File("apple.gif"));
            f.setIconImage(img);
        }
        catch (IOException e1)
        {
        }
        
        Object rows[][] = new Object[itemList.size()][4];
        for (int i = 0; i < itemList.size(); i++)
        {
            UserInfo item = itemList.get(i);
            item.setRowIndex(i);
            rows[i][0] = item.getGovernmentId();
            rows[i][1] = item.getLastName() + " " + item.getFirstName();
            rows[i][2] = item.getSkuName();
            rows[i][3] = item.getEmailAddress();
        }
        
        TableModel model = new DefaultTableModel(rows, columns)
        {
            private static final long serialVersionUID = 1L;

            @SuppressWarnings("rawtypes")
            public Class getColumnClass(int column)
            {
                return String.class;
            }
        };
        
        table.setModel(model);
        table.setEnabled(false);
        table.getColumnModel().getColumn(STATUS_INDEX).setCellRenderer(new MyProgressBarRenderer());
        JScrollPane tablePane = new JScrollPane(table);
        content.add(tablePane, BorderLayout.CENTER);
        
        final JButton checkResultBtn = new JButton("检查结果");
        final JButton runBtn = new JButton("运行");
        final JLabel label = new JLabel(LABEL_TEXT);
        runBtn.setEnabled(itemList.size() > 0);
        runBtn.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                shutdownBox.setEnabled(false);
                checkResultBtn.setEnabled(false);
                successCount = 0;
                JButton button = (JButton) e.getSource();
                button.setEnabled(false);
                ClockThread ct = new ClockThread(label);
                ct.setPriority(Thread.MAX_PRIORITY);
                ct.start();
                new Thread()
                {
                    public void run()
                    {
		                for (int i = 0; i < itemList.size(); i++)
		                {
		                    UserInfo item = itemList.get(i);
		                    getPostDataThread(table, i, item, postDataList);
		                }
		                sendMessages(itemList);
                    }
                }.start();
            }
         });
        
        checkResultBtn.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                runBtn.setEnabled(false);
                JButton button = (JButton) e.getSource();
                button.setEnabled(false);
                new Thread()
                {
                    public void run()
                    {
                        for (int i = 0; i < itemList.size(); i++)
                        {
                            UserInfo item = itemList.get(i);
                            checkResult(table, i, item);
                        }
                    }
                }.start();
            }
         });
        
        JPanel actionPane = new JPanel();        
        actionPane.setLayout(new GridLayout(1, 2));
        JPanel btnPane = new JPanel();
        btnPane.setLayout(new BorderLayout());
        btnPane.add(label, BorderLayout.EAST);
        btnPane.add(shutdownBox, BorderLayout.WEST);
        btnPane.setBorder(new EmptyBorder(10, 10, 10, 20));
        JPanel labelPane = new JPanel();
        labelPane.setLayout(new BorderLayout());
        labelPane.add(runBtn, BorderLayout.WEST);
        labelPane.add(checkResultBtn, BorderLayout.EAST);
        labelPane.setBorder(new EmptyBorder(10, 20, 10, 10));
        actionPane.add(btnPane);
        actionPane.add(labelPane);
        content.add(actionPane, BorderLayout.SOUTH);
        f.setVisible(true);
    }
    
    private static void getPostDataThread(final JTable table, final int rowIndex,
            final UserInfo item, final List<Map<String, String>> postDataList)
    {
        table.getModel().setValueAt(STEP_ONE, rowIndex, STATUS_INDEX);
        LogUtil.getInstance().writeLog("start getPostData:" + item.getGovernmentId());
        Map<String, String> postData = PostDataMgr.getInstance().getPostData(item);
        LogUtil.getInstance().writeLog("end getPostData:" + item.getGovernmentId());
        postDataList.add(postData);
        table.getModel().setValueAt(STEP_TWO, rowIndex, STATUS_INDEX);
    }
    
    private static void checkResult(final JTable table, final int rowIndex,
            final UserInfo item)
    {
        table.getModel().setValueAt(CHECKING, rowIndex, STATUS_INDEX);
        CheckResultMail checkResultMail = new CheckResultMail(item.getEmailAddress(), null);
        boolean isBingo = checkResultMail.isBingo();
        table.getModel().setValueAt(isBingo ? CHECKED_SUCCESS : CHECKED_FAILED, rowIndex, STATUS_INDEX);
    }

    private static class MyProgressBarRenderer extends JProgressBar implements
            TableCellRenderer
    {
        private static final long serialVersionUID = 1L;

        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column)
        {
            if (STEP_ONE.equals(value))
            {
                setValue(25);
                setString((String) value);
            }
            else if (STEP_TWO.equals(value))
            {
                setValue(50);
                setString(STEP_TWO);
            }
            else if (STEP_THREE.equals(value))
            {
                setValue(75);
                setString(STEP_THREE);
            }
            else if (SUCCESS.equals(value))
            {
                setValue(100);
                setString(SUCCESS);
            }
            else if (CHECKING.equals(value))
            {
                setValue(50);
                setString(CHECKING);
            }
            else if (CHECKED_FAILED.equals(value) || CHECKED_SUCCESS.equals(value))
            {
                setValue(100);
                setString((String) value);
            }
            setForeground(Color.GREEN);
            setStringPainted(true);
            return this;
        }
    }

    private static class ClockThread extends Thread
    {
        long targetInMill = 0;
        private JLabel label;
        int hourOld, minOld, secOld;

        private ClockThread(JLabel label)
        {
            this.label = label;
            Properties pro = new Properties();
            try
            {
                InputStream str = new BufferedInputStream(new FileInputStream(
                        "conf.properties"));
                pro.load(str);
            }
            catch (FileNotFoundException e)
            {
            }
            catch (IOException e1)
            {
            }

            int hour = Integer.valueOf(pro.getProperty("hour", "8"));
            int min = Integer.valueOf(pro.getProperty("min", "59"));
            int sec = Integer.valueOf(pro.getProperty("sec", "59"));
//            nextTime = Integer.valueOf(pro.getProperty("sleeptime", "50"));
            Calendar c = new GregorianCalendar();
            long startInMill = c.getTimeInMillis();
            c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH),
                    c.get(Calendar.DATE), hour, min, sec);
            targetInMill = c.getTimeInMillis();
            if (targetInMill < startInMill)
            {
                targetInMill += 3600 * 24 * 1000;
            }
        }

        public void run()
        {
            while (true)
            {
                Calendar today = new GregorianCalendar();
                long todayInMill = today.getTimeInMillis();
                long dd = targetInMill - todayInMill;
                long dis = dd / 1000;
                boolean isChange = false;
                int hour = (int) (dis % (3600 * 24) / 3600);
                if (hour != hourOld)
                {
                    isChange = true;
                    hourOld = hour;
                }
                int min = (int) (dis % 3600 / 60);
                if (min != minOld)
                {
                    isChange = true;
                    minOld = min;
                }
                int sec = (int) (dis % 60);
                if (sec != secOld)
                {
                    isChange = true;
                    secOld = sec;
                }
                String s = intToString(hour) + " 小时 " + intToString(min)
                        + " 分 " + intToString(sec) + " 秒";
                if (isChange)
                {
                    label.setText(LABEL_TEXT + s);
                }
                if (dd <= 100)
                {
                    book();
                    shutdown(false);
                    break;
                }
                try
                {
                    Thread.sleep(100);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }

        private String intToString(int i)
        {
            if (i < 10)
            {
                String str = "0" + i;
                return str;
            }
            else
            {
                return i + "";
            }
        }
    }

    private static void book()
    {
        for (int i = 0; i < postDataList.size(); i++)
        {
            Map<String, String> postData = postDataList.get(i);
            bookThread(postData);
            count++;
            try
            {
                if (count >= 8)
                {
                    nextTime = 50;
                }
                Thread.sleep(nextTime);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }

    private static void bookThread(final Map<String, String> postData)
    {
        new Thread()
        {
            public void run()
            {
                String governmentId = postData.get("governmentId");
                LogUtil.getInstance().writeLog("run book:" + governmentId);
                String rowIndex = postData.get("rowIndex");
                table.getModel().setValueAt(STEP_THREE, Integer.valueOf(rowIndex), STATUS_INDEX);
                if (isSend)
                {
	                RunTask.book(postData, governmentId);
                }
                else
                {
                    try
                    {
                        Thread.sleep(1500);
                    }
                    catch (InterruptedException e)
                    {
                    }
                }
                table.getModel().setValueAt(SUCCESS, Integer.valueOf(rowIndex), STATUS_INDEX);
                synchronized (lockObj)
                {
                    successCount++;
                    LogUtil.getInstance().writeLog("successCount:"+successCount+",postDataList.size:"+postDataList.size());
                    if (successCount == postDataList.size())
                    {
                        LogUtil.getInstance().writeLog("success all");
                        shutdown(true);
                    }
                }
            }
        }.start();
    }
    
    private static void shutdown(boolean isNow)
    {
        try
        {
            boolean isShutdown = shutdownBox.isSelected();
            LogUtil.getInstance().writeLog("isShutdown:" + isShutdown);
            if (isShutdown)
            {
                if (isNow)
                {
                    Runtime.getRuntime().exec("Shutdown -s -t 3");
                    System.exit(0);
                }
                else
                {
                    Runtime.getRuntime().exec(SHUTDOWN_CMD);
                }
            }
        }
        catch (IOException e)
        {
        }
    }
    
    private static void sendMessages(List<UserInfo> itemList)
    {
        Properties prop = new Properties();
        Session session = Session.getDefaultInstance(prop);
        final String to = "junhe3328@163.com";
        final String pwd = "250061";
        try
        {
            Store store = session.getStore("pop3");
            store.connect("pop3.163.com", to, pwd);
            Folder folder = store.getFolder("Inbox");
            folder.open(Folder.READ_ONLY);
            Message message[] = folder.getMessages();
            for (int i = 0; i < message.length; i++)
            {
                String subject = getSubject(message[i]);
                if (subject.indexOf("reserve:stop") >= 0)
                {
                    isSend = false;
                }
            }

            StringBuilder sendMessage = new StringBuilder();
            for (int i = 0; i < itemList.size(); i++)
            {
                UserInfo item = itemList.get(i);
                if (i != 0)
                {
                    sendMessage.append("\n");
                }
                sendMessage.append(item.getGovernmentId()).append(",")
                        .append(item.getLastName()).append(" ")
                        .append(item.getFirstName()).append(",")
                        .append(item.getSkuName()).append(",")
                        .append(item.getEmailAddress());
            }

            prop.setProperty("mail.transport.protocol", "smtp");  
            prop.setProperty("mail.smtp.auth", "true");  
            prop.setProperty("mail.host", "smtp.163.com");  
            session = Session.getInstance(prop, new Authenticator()
            {
                protected PasswordAuthentication getPasswordAuthentication()
                {
                    return new PasswordAuthentication(to, pwd);
                }
            });
            session.setDebug(false);
            MimeMessage mes = new MimeMessage(session);
            mes.setFrom(new InternetAddress(to));
            InternetAddress[] address = { new InternetAddress(to) };
            mes.setRecipients(Message.RecipientType.TO, address);
            mes.setSubject("今日预定 " + itemList.size() + " 单");
            mes.setSentDate(new Date());
            mes.setText(sendMessage.toString());
            Transport.send(mes);

            folder.close(false);
            store.close();
        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }
    
    private static String getSubject(Message message)
    {
        try
        {
            return MimeUtility.decodeText(message.getSubject());
        }
        catch (UnsupportedEncodingException e)
        {
        }
        catch (MessagingException e)
        {
        }
        return "";
    }
}
